﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using OthelloCognition;
using OthelloGame;
namespace OthelloGUI
{
    public partial class Othello : Form
    {
        public Othello()
        {
            InitializeComponent();
        }
 
        #region PrivateMembers
        private AbstractSolver blackPlayer, whitePlayer;
        OthelloGameBoard board = new OthelloGameBoard();
        List<Button> places = new List<Button>(64);
        List<OthelloGameBoard> history = new List<OthelloGameBoard>();
        int currentHistoricalBoard = 0;

        int turnTime = 100;

        #endregion

        #region events

        private void Othello_Load(object sender, EventArgs e)
        {
            Thread.CurrentThread.Priority = ThreadPriority.Highest;
            drawAllButtons();
            drawboard(board);
            setupSelections();
        }
        private void ddlPlayerOne_SelectedIndexChanged(object sender, EventArgs e)
        {
            blackPlayer = NewSolver.NewSolverConstructor((SolverEnum)((ComboBox)sender).SelectedValue);
        }
        private void btnStartGame_Click(object sender, EventArgs e)
        {
            //remove buttons
            foreach (Button btn in places)
            {
                this.Controls.Remove(btn);
            }

            history = new List<OthelloGame.OthelloGameBoard>();
            board = new OthelloGameBoard();
            places = new List<Button>(64);

            drawAllButtons();
            drawboard(board);

            takeAgentTurn();
        }
        private void ddlPlayerTwo_SelectedIndexChanged(object sender, EventArgs e)
        {
            whitePlayer = NewSolver.NewSolverConstructor((SolverEnum)((ComboBox)sender).SelectedValue);
        }

        private void ddlSecondsForPlay_SelectedIndexChanged(object sender, EventArgs e)
        {
            turnTime = int.Parse(((ComboBox)sender).SelectedItem.ToString());
        }

        #endregion

        #region PlayerManagment
        private void setupSelections()
        {


            ddlPlayerOne.Items.Clear();
            ddlPlayerTwo.Items.Clear();
            ddlPlayerOne.ValueMember = "Key";
            ddlPlayerOne.DisplayMember = "Value";
            ddlPlayerTwo.ValueMember = "Key";
            ddlPlayerTwo.DisplayMember = "Value";
            ddlPlayerOne.DataSource = EnumHelper.ToList(typeof(SolverEnum));
            ddlPlayerTwo.DataSource = EnumHelper.ToList(typeof(SolverEnum));
        }

        #endregion

        #region board managment
         bool thumbnailFakeCallback() { return true; }
        private string displayScores(OthelloGame.OthelloGameBoard boardToTally)
        {
            string score;
            if (boardToTally.WhiteCount > boardToTally.BlackCount)
            {
                score = "White wins with " + boardToTally.WhiteCount.ToString() + " points over Blacks " + boardToTally.BlackCount + " points.";

                whitePlayer.recordResult(true);
                blackPlayer.recordResult(false);
            }
            else if (boardToTally.WhiteCount < boardToTally.BlackCount)
            {
                score = "Black wins with " + boardToTally.BlackCount.ToString() + " points over Whites " + boardToTally.WhiteCount + " points.";
                whitePlayer.recordResult(false);
                blackPlayer.recordResult(true);
            }
            else
            {
                score = "Black and White tie with " + boardToTally.BlackCount.ToString() + " points";
                whitePlayer.recordResult(false);
                blackPlayer.recordResult(false);
            }
            return score;
        }
        private void drawboard(OthelloGame.OthelloGameBoard boardToDraw)
        {
            this.Refresh();
            if (this.chkPlayWIthUI.Checked)
            {
                OthelloGame.OthelloBoardLocation locationsToCheck;
                OthelloGame.OthelloBoardGamePiece pieceInPlace;
                Button buttonToChange;
                this.label1.Text = "It's " + boardToDraw.PlayersTurn.ToString() + "'s turn.";
                if (boardToDraw.GameOver())
                {
                    this.label1.Text = displayScores(boardToDraw);
                }
                for (int horizontalIndex = 0; horizontalIndex < 8; horizontalIndex++)
                {
                    for (int verticalIndex = 0; verticalIndex < 8; verticalIndex++)
                    {
                        locationsToCheck = new OthelloGame.OthelloBoardLocation(horizontalIndex, verticalIndex);
                        pieceInPlace = boardToDraw.ExamineBoard(locationsToCheck);
                        Image.GetThumbnailImageAbort callback = new Image.GetThumbnailImageAbort(thumbnailFakeCallback);
                        IntPtr callData = new IntPtr();

                        Image blackBall = OthelloGUI.Properties.Resources.blackBall.GetThumbnailImage(50, 50, callback, callData);
                        Image whiteBall = OthelloGUI.Properties.Resources.whiteBall.GetThumbnailImage(50, 50, callback, callData);

                        buttonToChange = places.ElementAt((horizontalIndex * 8) + verticalIndex);
                        if (pieceInPlace != null)
                        {
                            if (pieceInPlace.IsBlack)
                            {
                                // RuntimeResMan.Resources r = new Resources(Assembly.GetExecutingAssembly());
                                //r
                                //TODO: fix static reference
                                //OthelloGUI.Properties.Resources.ResourceManager.GetObject("");
                                buttonToChange.Image = blackBall;

                            }
                            else
                            {
                                //OthelloGUI.Properties.Resources.ResourceManager.GetObject("D:\Personal Documents\Visual Studio 2008\Projects\OthelloGameBoard\OthelloGUI\images\whiteBall.jpg");
                                buttonToChange.Image = whiteBall;
                            }
                        }
                        else
                        {
                            if (boardToDraw.AvailableOptionLocations.Contains(locationsToCheck))
                            {
                                buttonToChange.BackColor = Color.GreenYellow;
                            }
                            else
                            {
                                buttonToChange.BackColor = Color.Tan;
                            }
                        }
                    }
                }
            }
            this.Refresh();
        }
        private OthelloCognition.AbstractSolver currentPlayer
        {
            get
            {
                if (board.PlayersTurn == OthelloGame.PieceColors.Black)
                {
                    return blackPlayer;
                }
                else
                {
                    return whitePlayer;
                }
            }
        }
        #endregion
   
        #region button managment
        private void drawAllButtons()
        {
            Button currentButton;
         
            for (int indexHorizon = 0; indexHorizon < 8; indexHorizon++)
            {
                for (int indexVertical = 0; indexVertical < 8; indexVertical++)
                {
                    currentButton = new Button();
                    setupButtonLook(currentButton);
                    currentButton.Left = indexHorizon * 50;
                    currentButton.Top = (indexVertical * 50) + 14;
                    currentButton.Click += new System.EventHandler(this.button_Click);
                    
                    this.Controls.Add(currentButton);
                    places.Add(currentButton);
                }
            }
        }
        private void setupButtonLook(Button buttonToMakeOver)
        {
            buttonToMakeOver.Height = 50;
            buttonToMakeOver.Width = 50;
            buttonToMakeOver.Text = String.Empty;
        }
        private void button_Click(object sender, EventArgs e)
        {
            if (currentPlayer.SolverName() == SolverEnum.Human)
            {
                OthelloGame.OthelloBoardLocation buttonSpot;
                int hSpot;
                int vSpot;
                int arraySpot = places.IndexOf((Button)sender);
                hSpot = Convert.ToInt32(Math.Floor(arraySpot / 8.0));
                vSpot = Convert.ToInt32(arraySpot % 8);
                buttonSpot = new OthelloGame.OthelloBoardLocation(hSpot, vSpot);
// PAG               PlayHumanMove(buttonSpot);
                playMove(buttonSpot);
                takeAgentTurn();
            }
        }

        #endregion 

        #region PAG

        private void takeAgentTurn()
        {
            while (currentPlayer.SolverName() != SolverEnum.Human && !board.GameOver())
            {
                Thread playerThread = new Thread(new ThreadStart(computeNextAgentMove));
                playerThread.Name = "Move " + (board.WhiteCount + board.BlackCount - 4);
                playerThread.Start();

                Thread.CurrentThread.Join(turnTime);
                try
                {
                    playerThread.Abort();
                }
                catch
                {
                    // Ignore, just stopping player's turn
                }
                 
                OthelloBoardLocation move = currentPlayer.nextMove;
                playMove(move);
            }
        }

        private void playMove(OthelloGame.OthelloBoardLocation nextMove)
        {
            if (board.AvailableOptionLocations.Contains(nextMove))
            {
                board.PlacePit(nextMove);
                drawboard(board);
                this.Refresh();
            }
        }

        private void computeNextAgentMove()
        {
            currentPlayer.searchGameState(board);
        }
        #endregion
     

        private void btnPrevious_Click(object sender, EventArgs e)
        {
            currentHistoricalBoard--;
            drawboard(history[currentHistoricalBoard]);
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            currentHistoricalBoard++;
            drawboard(history[currentHistoricalBoard]);
        
        }

        private void turnTimeBox_TextChanged(object sender, EventArgs e)
        {
            int sec = int.Parse(((MaskedTextBox)sender).Text);
            turnTime = sec;
        }
 
    }

       
}
